#ifndef xarg_i
    #error "xarg_i missing"
#endif

#define __xstr0(...)     #__VA_ARGS__
#define __xstr1(...)    __xstr0(__VA_ARGS__)

xtest("mix_buffer<uxx, " __xstr1(xarg_i) ">"){
    using mix_buffer            = inc::mix_buffer<uxx, xarg_i>;

    // 测试 push(item_t)
    auto used_bytes             = inc::memory::used_bytes();
    {
        mix_buffer buffer;

        for(auto i = uxx{}; i < 1024; i++){
            buffer.push(i);
            xassert_eq(buffer->length, i + 1);
            xassert_eq(buffer[i], i);
        }

        buffer.foreach([&](uxx i, uxx item){
            xassert_eq(i, item);
        });

        for(uxx i = 0; i < buffer->length; i++){
            xassert_eq(i, buffer[i]);
        }
    }

    xassert_eq(used_bytes, inc::memory::used_bytes());



    // 测试 push({...})
    {
        mix_buffer buffer;

        for(auto i = uxx{}; i < 1024 * 9; i += 9){
            buffer.push({ i + 0, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, i + 8, });
            xassert_eq(buffer->length, i + 9);

            for(uxx j = i; j < i + 9; j++){
                xassert_eq(buffer[j], j);
            }
        }

        buffer.foreach([&](uxx i, uxx item){
            xassert_eq(i, item);
        });

        for(uxx i = 0; i < buffer->length; i++){
            xassert_eq(i, buffer[i]);
        }
    }

    xassert_eq(used_bytes, inc::memory::used_bytes());

    // 测试静态分配 lend
    {
        mix_buffer buffer;
        inc::counter            counter;
        uxx                     total_length;

        for(auto i = 0, j = i; i < 10; j = i, i++){
            auto length         = uxx(1) << j;
            auto temp           = buffer.lend(length);
            xassert_eq(temp->is_requires_free, false);
            xassert_eq(temp->is_requires_destruction, false);

            for(uxx j = 0; j < temp->length; j++){
                temp[j]         = counter;
                total_length    = temp[j] + 1;
            }

            xassert_eq(buffer->length, total_length);
        }

        buffer.foreach([&](uxx i, uxx item){
            xassert_eq(i, item);
        });

        xassert_eq(buffer->length, total_length);
    }

    xassert_eq(used_bytes, inc::memory::used_bytes());



    // 测试混合分配 lend
    {
        mix_buffer buffer;
        inc::counter            counter;
        uxx                     total_length;

        for(auto i = uxx{}, j = i ; i < 1024; j = i, i = i * 3 / 2 + 1){
            auto length         = j + 1;
            auto temp           = buffer.lend(length);
            xassert_eq(temp->length, length);

            for(uxx j = 0; j < temp->length; j++){
                temp[j]         = counter;
                total_length    = temp[j] + 1;
            }

            if (temp->is_requires_free){
                buffer.push(temp);
            }

            xassert_eq(buffer->length, total_length);
        }

        buffer.foreach([&](uxx i, uxx item){
            xassert_eq(i, item);
        });

        auto items              = new uxx[buffer->length];
        auto seq                = inc::seqptr<uxx>(items, buffer->length);
        buffer.copy_to(seq);

        seq.foreach([&](uxx i, uxx item){
            xassert_eq(i, item);
        });

        delete[] items;
        xassert_eq(buffer->length, total_length);
    }

    xassert_eq(used_bytes, inc::memory::used_bytes());




    // 测试 static_buffer
    {
        inc::mix_buffer<uxx, 128> buffer;
        auto temp0              = buffer.lend(127);
        auto temp1              = buffer.lend(127);
        auto temp2              = buffer.lend(127);

        xassert_eq(temp0->is_requires_free, false);
        xassert_eq(temp1->is_requires_free, true);
        xassert_eq(temp2->is_requires_free, true);
        xassert_eq(temp0.m_ptr, uxxp(buffer.m_first_page));
        xassert_eq(temp1.m_ptr, uxxp(buffer.m_static_buffer));
        xassert_ne(temp2.m_ptr, uxxp(buffer.m_first_page));
        xassert_ne(temp2.m_ptr, uxxp(buffer.m_static_buffer));

        // 提前释放
        temp1                   = nullptr;
        temp2                   = buffer.lend(127);
        xassert_eq(temp2.m_ptr, uxxp(buffer.m_static_buffer));
    }



    // 测试 operator[]
    {
        mix_buffer buffer;

        for(uxx i = 0; i < 4096; i++){
            buffer.push(i);
        }

        for(uxx i = 0; i < 4096; i++){
            xassert_eq(buffer[i], i);
        }
    }
};

#undef xarg_i
#undef __xstr0
#undef __xstr1
